﻿#-------------------------------------------------------------------------------
# Copyright 2011 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
#$Id$
#$Author$
#$Date$
#$Rev$
#$URL$
#-------------------------------------------------------------------------------

#1. 特殊方法
# 在类中有一些特殊的方法具有特殊的意义，如__init__和__del__方法。通常，特殊方法都被用来模仿某个行为。如果你要为你的类使用x[key]这样的索引操作，那么你只需要实现__getitem__()方法即可。
#名称                      说明
#__init__(self, ...)     这个方法在新建对象恰好要被返回使用之前被调用。
#__del__(self)	         恰好在对象要被删除之前调用。
#__str__(self)           在我们对对象使用print语句或是使用str()的时候调用。
#__lt__(self, other)     当使用 小于 运算符（<）的时候调用。类似地，对于所有的运算符（+，>等等）都有特殊的方法。
#__getitem__(self, key)  使用x[key]索引操作符的时候调用。
#__len__(self)           对序列对象使用内建的len()函数的时候调用。
#-------------------------------------------------------------------------------
#2. 单语句块
#一般，每个语句块都是通过它的缩进层次与其他语句块分开的。然而，有时候你的语句块只包含一句语句，那么你可以在条件语句或循环语句的同一行指明它。

flag = True
if flag: print("Yes")

#虽然这样做可以使你的程序变得小一些 ，但是除了检验错误之外我强烈建议你不要使用这种缩略方法。不使用它的一个主要的理由是一旦你使用了恰当的缩进，你就可以很方便地添加一个额外的语句。

#-------------------------------------------------------------------------------
#3. 列表综合
#通过列表综合，可以从一个已有的列表导出一个新的列表。例如，你有一个数的列表，而你想要得到一个对应的列表，使其中所有大于2的数都是原来的2倍。对于这种应用，列表综合是最理想的方法。

listone = [2, 3, 4]
listtwo = [2 * i for i in listone if i > 2]
print(listtwo)

#这段话的意思是：将listone中的所有大于2的数分别乘以2，得出一个新的listtwo。运行结果：
#[6, 8]

#-------------------------------------------------------------------------------
#4. 在函数中接收元组和列表
#当要使函数接收元组或字典形式的参数的时候，有一种特殊的方法，它分别使用*和**前缀。这种方法在函数需要获取可变数量的参数的时候特别有用。

def powersum(power, *args):
    '''Return the sum of each argument raised to specified power.'''
    total = 0
    for i in args:
        total += pow(i, power)
    return total

#由于在args变量前有*前缀，所有多余的函数参数都会作为一个元组存储在args中。如果使用的是**前缀，多余的参数则会被认为是一个字典的键/值对。

#-------------------------------------------------------------------------------
#5. lambda形式
#lambda语句被用来创建新的函数对象，并且在运行时返回它们。
def make_repeater(n):
    return lambda s : s * n

twice = make_repeater(2)
print(twice("ha"))
print(twice(5))

#运行结果：
#haha
#10
#这里，我们使用了make_repeater函数在运行时创建新的函数对象，并且返回它。lambda语句用来创建函数对象。本质上，lambda需要一个参数，后面仅跟单个表达式作为函数体，而表达式的值被这个新建的函数返回。注意，即便是print语句也不能用在lambda形式中，只能使用表达式。

#-------------------------------------------------------------------------------
#6. exec和eval语句
#exec语句用来执行储存在字符串或文件中的Python语句。例如，我们可以在运行时生成一个包含Python代码的字符串，然后使用exec语句执行这些语句。
exec("print('Hello World')")
#运行结果：
#Hello World
#eval语句用来计算存储在字符串中的有效Python表达式。
eval("2 * 3")
#运行结果：
#6

#-------------------------------------------------------------------------------
#7. assert语句
#assert语句用来声明某个条件是真的。例如，如果你非常确信某个你使用的列表中至少有一个元素，而你想要检验这一点，并且在它非真的时候引发一个错误，那么assert语句是应用在这种情形下的理想语句。当assert语句失败的时候，会引发一个AssertionError。
#>>> mylist = ["item"]
#>>> assert(len(mylist) >= 1)
#>>> mylist.pop()
#'item'
#>>> assert(len(mylist) >= 1)
#Traceback (most recent call last):
#  File "<pyshell#13>", line 1, in <module>
#    assert(len(mylist) >= 1)
#AssertionError

#-------------------------------------------------------------------------------
#8. repr函数
#repr函数用来取得对象的规范字符串表示。注意，在大多数时候有eval(repr(object)) == object。
#>>> i = []
#>>> i.append("item")
#>>> repr(i)
#"['item']"
#基本上，repr函数和反引号用来获取对象的可打印的表示形式。你可以通过定义类的__repr__方法来控制你的对象在被repr函数调用的时候返回的内容。